import React, {useCallback, useEffect, useMemo, useRef} from 'react'

interface ModalProps {
  isOpen: boolean
  onClose: () => void | Promise<void>
  size?: 'sm' | 'lg' | 'xs'
  closeOnEscape?: boolean
  isBackdropColor?: boolean
  className?: string
  classNameWrapper?: string
}

const Modal: React.FC<ModalProps> = ({
  isOpen,
  onClose,
  size,
  closeOnEscape,
  isBackdropColor,
  className,
  children,
  classNameWrapper,
}): React.ReactElement => {
  const escFunction = useCallback(
    (event: any) => {
      if (event.keyCode === 27) {
        onClose && onClose()
      }
    },
    [onClose],
  )

  const closeModal = useCallback(() => {
    onClose()
    document.removeEventListener('keydown', escFunction, false)
  }, [escFunction, onClose])

  const onClickContent = useCallback((evt: any) => {
    evt.stopPropagation()
  }, [])

  const backdropRef = useRef()

  const onClickBackdrop = useCallback(
    (evt) => {
      let path = null
      if (evt.nativeEvent.path) {
        if (evt.nativeEvent.composedPath) {
          path = evt?.nativeEvent?.path[0] || evt.nativeEvent.composedPath
        } else {
          path = evt?.nativeEvent?.path[0]
        }
      } else if (evt.nativeEvent.composedPath) {
        path = evt.nativeEvent.composedPath()[0]
      } else {
        path = null
        console.log('Supports neither `path` nor `composedPath`')
      }
      if (!!onClose && path && path === backdropRef?.current) {
        closeModal()
      }
    },
    [onClose, closeModal],
  )

  const onScroll = useCallback((evt: any) => {
    evt.stopPropagation()
  }, [])

  useEffect(() => {
    if (isOpen) {
      let newCloseOnEscape = closeOnEscape !== undefined ? closeOnEscape : true
      if (newCloseOnEscape) {
        document.addEventListener('keydown', escFunction, false)
      }
    }
  }, [closeOnEscape, escFunction, isOpen])

  const renderContent = useMemo(() => {
    let newIsBackdropColor: boolean = isBackdropColor
    if (isBackdropColor === null || isBackdropColor === undefined) {
      newIsBackdropColor = true
    }
    const classNameResult: string =
      'modal ' +
      (isOpen ? 'open ' : ' ') +
      (newIsBackdropColor ? 'backdrop-color ' : ' ') +
      (classNameWrapper ? classNameWrapper : ' ')
    return (
      <div
        ref={backdropRef}
        className={classNameResult}
        onMouseDown={(event) => {
          onClickBackdrop(event)
        }}>
        <div
          className={
            'modal-content modal-content-admin ' +
            (size ? size + ' ' : ' ') +
            (className ? className : ' ')
          }
          onClick={onClose ? onClickContent : undefined}
          onScroll={onScroll}>
          {children}
        </div>
      </div>
    )
  }, [
    isBackdropColor,
    isOpen,
    classNameWrapper,
    onClickBackdrop,
    size,
    className,
    onClose,
    onClickContent,
    onScroll,
    children,
  ])

  return <>{renderContent}</>
}

export {Modal}
